#pragma once
#include <iostream>
#include <string>
#include <signal.h>
#include "runner.hpp"
#include "complier.hpp"
#include <jsoncpp/json/json.h>
#include "../comm/Log.hpp"
#include "../comm/util.hpp"


namespace complie_runNs {
    using namespace logNs;
    using namespace utilNs;
    using namespace complierNs;
    using namespace runnerNs;
    class Complie_Run {
    public :
        // 删除所有临时文件
        static void RemoveTempFile(const std::string& file_name) {
            if (FileUtil::IsExistFile(PathUtil::ComplieErr(file_name))) {
                unlink(PathUtil::ComplieErr(file_name).c_str());
            }

            if (FileUtil::IsExistFile(PathUtil::Src(file_name))) {
                unlink(PathUtil::Src(file_name).c_str());
            }

            if (FileUtil::IsExistFile(PathUtil::Exe(file_name))) {
                unlink(PathUtil::Exe(file_name).c_str());
            }

            if (FileUtil::IsExistFile(PathUtil::Stdin(file_name))) {
                unlink(PathUtil::Stdin(file_name).c_str());
            }

            if (FileUtil::IsExistFile(PathUtil::Stdout(file_name))) {
                unlink(PathUtil::Stdout(file_name).c_str());
            }

            if (FileUtil::IsExistFile(PathUtil::Stderr(file_name))) {
                unlink(PathUtil::Stderr(file_name).c_str());
            }
        }
        static std::string CodeToDesc(int status_code, const std::string& file_name) {
            std::string desc;
            switch (status_code) {
                case 0 : 
                    desc = "运行成功!";
                    break;
                case -1 :
                    desc = "提交代码为空"; 
                    break;
                case -2 :
                    desc = "内部错误"; 
                    break;
                case -3 : 
                    {
                        FileUtil::ReadeFile(PathUtil::ComplieErr(file_name), &desc);
                        desc = "编译报错\n" + desc;
                        break;                        
                    }
                case -5 :
                    {
                        FileUtil::ReadeFile(PathUtil::ComplieErr(file_name), &desc);
                        desc = "编译告警\n" + desc;
                        break;                        
                    }
                case -4 : 
                    desc = "内部错误";
                    break;
                case SIGXCPU : 
                    desc = "运行超时";
                    break;
                case SIGFPE :
                    desc = "浮点数溢出";
                    break;
                case SIGABRT : 
                    desc = "内存超出范围";
                    break;
                case SIGSEGV :
                    desc = "段错误，可能是数组越界,野指针等问题";
                    break;
                default :
                    desc = "未知错误:" + std::to_string(status_code);
                    break;
            }
            return desc;
        }
        static void Start(const std::string& in_json, std::string* out_json) {
            // 对in_json进行反序列化
            Json::Value in_value;
            Json::Reader reader;
            reader.parse(in_json, in_value);
            std::string code = in_value["code"].asString();
            std::string input = in_value["input"].asString();
            int cpu_limit = in_value["cpu_limit"].asInt();
            int mem_limit = in_value["mem_limit"].asInt();
            int status_code = 0;
            int run_result = 0;
            std::string file_name;
            if (code.empty()) {
                // 用户提交代码为空
                status_code = -1; // 表示用户提交的代码为空
                goto END;
            }


            // 获取一个唯一的文件名
            file_name = FileUtil::UniqueFileName();
            // 将代码和input都写入对应的文件
            if (!FileUtil::WriteFile(PathUtil::Src(file_name), code)) {
                status_code = -2; // 表示写入文件失败
                goto END;
            }
            if (!FileUtil::WriteFile(PathUtil::Stdin(file_name), input)) {
                status_code = -2; // 表示写入文件失败
            }

            // 开始编译
            if (!Complier::Complie(file_name)) {
                // 编译失败
                status_code = -3;
                goto END;
            } else {
                std::string complie_err_content;
                FileUtil::ReadeFile(PathUtil::ComplieErr(file_name), &complie_err_content);
                if (!complie_err_content.empty()) {
                    // 用户的代码有告警，同样也不让用户运行
                    status_code = -5; // 表示用户的代码编译有告警
                    goto END;
                }
            }
            
            // 开始运行
            run_result = Runner::Run(file_name, cpu_limit, mem_limit);

            if (run_result == -1) {
                status_code = -4; // 表示运行时，打开文件失败
            } else {
                status_code = run_result;
            }
            END:

            Json::Value out_value;
            Json::FastWriter writer;
            out_value["status"] = status_code;
            out_value["reason"] = CodeToDesc(status_code, file_name);
            if (status_code == 0) {
                std::string stdout_content;
                FileUtil::ReadeFile(PathUtil::Stdout(file_name), &stdout_content);
                out_value["stdout"] = stdout_content;
                std::string stderr_content;
                FileUtil::ReadeFile(PathUtil::Stderr(file_name), &stderr_content);
                out_value["stderr"] = stderr_content;
            }

            // 序列化
            *out_json = writer.write(out_value);
            RemoveTempFile(file_name);
        }
    };
    
};